#include "ThreadPool/log.hpp"
#include <cstdio>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>

void* readFunc(void* argc)
{
    pthread_detach(pthread_self());  // 自我分离
    char buffer[1024];
    int sock = *((int*)argc);
    while (true)
    {
        ssize_t n = read(sock, buffer, sizeof(buffer) - 1);
        if (n > 0)
        {
            buffer[n] = '\0';
            std::cout << buffer << std::endl;
        }
        else if (n == 0)
        {
            // 此时对端关闭，我也关闭即可
            break;
        }
        else
        {
            logMessage(FATAL, "接收服务器数据失败！%d-%s (file:%s func:%s line:%d)", errno, strerror(errno), __FILE__, __func__, __LINE__);
            exit(4);
        }
    }

    return nullptr;
}

static void UserManual()
{
    std::cout << "please:./TCPclient server_ip server_port" << std::endl;
}

int main(int argc, char* argv[])
{
    if (argc != 3)
    {
        UserManual();
        exit(-1);
    }

    // 创建客户端的套接字
    int clientSock = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSock < 0)
    {
        logMessage(FATAL, "套接字创建失败！%d-%s (file:%s func:%s line:%d)", errno, strerror(errno), __FILE__, __func__, __LINE__);
        exit(1);
    }

    // TCP客户端同样的不需要主动绑定自己的ip和port
    // 对于TCP客户端来说，需要的是连接能力，那么一个套接字足以
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof server_addr);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(argv[2]));  // 是要发送到网络上的，所以千万别忘了转为网络字节序
    if (0 > inet_aton(argv[1], &server_addr.sin_addr))  // 主机转网络 ip 点分十进制
    {
        logMessage(FATAL, "ip从本地转化网络字节序失败！%d-%s (file:%s func:%s line:%d)", errno, strerror(errno), __FILE__, __func__, __LINE__);
        exit(2);
    }
    socklen_t sever_len = sizeof server_addr;
    if ( 0 > connect(clientSock, (struct sockaddr*)&server_addr, sever_len))
    {
        logMessage(FATAL, "服务器连接失败！%d-%s (file:%s func:%s line:%d)", errno, strerror(errno), __FILE__, __func__, __LINE__);
        exit(3);
    }
    logMessage(NORMAL, "服务器连接成功~");

    // 客户端不断向服务器端发送信息接收信息即可
    std::string message;
    char buffer[1024];
    // 创建两个线程, 一个发送消息，一个接受服务端发来的消息 这样就会同步进行
    pthread_t pid;
    pthread_create(&pid, nullptr, readFunc, (void*)&clientSock);
    while (true)
    {
        printf("请输入# ");
        std::getline(std::cin, message);
        if (message == "quit") break;

        // 使用send可以发送
        if ( 0 > send(clientSock, message.c_str(), message.size(), 0))  // 阻塞发送
        {
            logMessage(ERROR, "客户端发送失败！%d-%s (file:%s func:%s line:%d)", errno, strerror(errno), __FILE__, __func__, __LINE__);
            continue;
        }
    }
    close(clientSock);
    return 0;
}